package com.fiona.remoting.netty.server;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fiona.core.message.Message;
import com.fiona.core.util.NetUtils;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

@Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
	private static Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

	private final Map<String, Channel> channels = new ConcurrentHashMap<String, Channel>();
	
	public Map<String, Channel> getChannels() {
		return channels;
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		// MessageProto.Message message = (MessageProto.Message) msg;
		Message message = (Message) msg;
		logger.debug("MessageKey:" + message.getMessageKey());
		// ping
		if (message.getType() == 1) {
			ctx.writeAndFlush(message);
		}

	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent event = (IdleStateEvent) evt;
			if (IdleState.READER_IDLE.equals(event.state())) { // 如果读通道处于空闲状态，说明没有接收到心跳命令
				System.out.println("关闭这个不活跃的channel：" + ctx.name());
				ctx.channel().close();
				channels.remove(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()));
			}
		} else {
			super.userEventTriggered(ctx, evt);
		}
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		Channel channel = ctx.channel();
		if (channel != null) {
			channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()), channel);
		}
	}
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
		channels.remove(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()));
	}
}
